# cron: 12 6 * * *
# new Env("豆芽代理更换白名单")
import os
import requests
import json
import time
import sys
import re
import urllib.parse
import datetime

# 环境变量配置
AUTH_KEY = os.getenv('AUTH_KEY')
PUSH_PLUS_TOKEN = os.getenv('PUSH_PLUS_TOKEN')

# API接口配置 - 使用正确的参数名 "white" 而不是 "ip"
GET_WHITE_URL = "https://api.douyadaili.com/proxy/?service=GetWhite&authkey={}"
DEL_WHITE_URL = "https://api.douyadaili.com/proxy/?service=DelWhite&authkey={}&white={}"
ADD_WHITE_URL = "https://api.douyadaili.com/proxy/?service=AddWhite&authkey={}&white={}"

# 持久化文件
LAST_IP_FILE = "last_ip.txt"
MAX_RETRIES = 3

def get_public_ip():
    """获取本机公网IP地址"""
    services = [
        'https://api.ipify.org',
        'https://ipinfo.io/ip',
        'https://ifconfig.me/ip',
        'https://checkip.amazonaws.com',
        'https://ip.seeip.org'
    ]
    
    for url in services:
        try:
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                ip = response.text.strip()
                # 验证IP格式
                if re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip):
                    return ip
        except Exception:
            continue
    return None

def get_white_list():
    """获取当前白名单列表"""
    url = GET_WHITE_URL.format(AUTH_KEY)
    try:
        response = requests.get(url, timeout=15)
        if response.status_code == 200:
            # 尝试解析为逗号分隔的IP列表
            if ',' in response.text:
                ips = [ip.strip() for ip in response.text.split(',') if ip.strip()]
                valid_ips = [ip for ip in ips if re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip)]
                if valid_ips:
                    return valid_ips
            
            # 尝试解析为JSON
            try:
                data = response.json()
                if isinstance(data, dict) and data.get('code') == 0:
                    return [ip.strip() for ip in data.get('data', [])]
                elif isinstance(data, list):
                    return [ip.strip() for ip in data]
            except json.JSONDecodeError:
                pass
            
            # 尝试其他格式
            ips = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', response.text)
            if ips:
                return list(set(ips))  # 去重
            
            print(f"无法解析白名单响应: {response.text[:100]}")
        else:
            print(f"获取白名单失败 - 状态码: {response.status_code}")
    except Exception as e:
        print(f"获取白名单异常: {str(e)}")
    return None

def del_white_ip(ip):
    """删除白名单IP"""
    # 注意：使用 "white" 参数而不是 "ip"
    url = DEL_WHITE_URL.format(AUTH_KEY, urllib.parse.quote(ip))
    
    try:
        response = requests.get(url, timeout=15)
        print(f"删除操作URL: {url}")
        print(f"删除操作响应: {response.text[:200]}")
        
        if response.status_code == 200:
            # 检查文本响应
            if '成功' in response.text or 'success' in response.text.lower():
                return True
            elif '失败' in response.text or 'fail' in response.text.lower():
                print(f"删除失败: {response.text}")
            else:
                print(f"无法确定删除结果: {response.text}")
        else:
            print(f"删除白名单失败 - 状态码: {response.status_code}")
    except Exception as e:
        print(f"删除白名单异常: {str(e)}")
    return False

def add_white_ip(ip):
    """添加白名单IP"""
    # 注意：使用 "white" 参数而不是 "ip"
    url = ADD_WHITE_URL.format(AUTH_KEY, urllib.parse.quote(ip))
    
    try:
        response = requests.get(url, timeout=15)
        print(f"添加操作URL: {url}")
        print(f"添加操作响应: {response.text[:200]}")
        
        if response.status_code == 200:
            # 检查文本响应
            if '成功' in response.text or 'success' in response.text.lower():
                return True
            elif '失败' in response.text or 'fail' in response.text.lower():
                print(f"添加失败: {response.text}")
            else:
                print(f"无法确定添加结果: {response.text}")
        else:
            print(f"添加白名单失败 - 状态码: {response.status_code}")
    except Exception as e:
        print(f"添加白名单异常: {str(e)}")
    return False

def read_last_ip():
    """读取上次记录的IP"""
    if os.path.exists(LAST_IP_FILE):
        try:
            with open(LAST_IP_FILE, 'r') as f:
                return f.read().strip()
        except:
            return None
    return None

def save_last_ip(ip):
    """保存当前IP到文件"""
    with open(LAST_IP_FILE, 'w') as f:
        f.write(ip)

def push_notification(message):
    """通过PushPlus发送通知"""
    if not PUSH_PLUS_TOKEN:
        print("未配置PUSH_PLUS_TOKEN，跳过通知")
        return
    
    url = "http://www.pushplus.plus/send"
    headers = {"Content-Type": "application/json"}
    payload = {
        "token": PUSH_PLUS_TOKEN,
        "title": "白名单更新通知",
        "content": message
    }
    
    try:
        response = requests.post(url, json=payload, headers=headers, timeout=10)
        if response.status_code == 200:
            print("通知发送成功")
        else:
            print(f"通知发送失败: {response.text}")
    except Exception as e:
        print(f"通知发送异常: {str(e)}")

def main():
    # 检查环境变量
    if not AUTH_KEY:
        print("错误: 未设置AUTH_KEY环境变量")
        push_notification("错误: 未设置AUTH_KEY环境变量")
        sys.exit(1)
    
    retry_count = 0
    success = False
    current_ip = None
    
    # 记录开始时间
    start_time = datetime.datetime.now()
    print(f"## 开始执行... {start_time.strftime('%Y-%m-%d %H:%M:%S')}\n")
    
    while retry_count < MAX_RETRIES and not success:
        retry_count += 1
        print(f"\n===== 尝试第 {retry_count} 次 =====")
        
        # 1. 获取当前公网IP
        current_ip = get_public_ip()
        if not current_ip:
            print("错误: 无法获取公网IP")
            time.sleep(5)
            continue
        print(f"当前公网IP: {current_ip}")
        
        # 2. 获取白名单列表
        white_list = get_white_list()
        if white_list is None:
            print("错误: 获取白名单失败")
            time.sleep(5)
            continue
        print(f"当前白名单: {', '.join(white_list)}")
        
        # 3. 检查当前IP是否已在白名单
        if current_ip in white_list:
            print("✅ 当前IP已在白名单中")
            
            # 清理旧IP（如果存在）
            last_ip = read_last_ip()
            if last_ip and last_ip != current_ip and last_ip in white_list:
                print(f"发现旧IP {last_ip}，尝试清理...")
                if del_white_ip(last_ip):
                    print(f"清理操作返回成功: {last_ip}")
                    # 验证清理结果
                    time.sleep(3)
                    new_white_list = get_white_list()
                    if new_white_list and last_ip not in new_white_list:
                        print(f"✅ 清理成功: 旧IP {last_ip} 已移除")
                    else:
                        print(f"⚠️ 清理失败: 旧IP {last_ip} 仍在白名单中")
                else:
                    print(f"清理旧IP失败: {last_ip}")
            
            save_last_ip(current_ip)
            success = True
            break
        
        # 4. 检查上次记录的IP
        last_ip = read_last_ip()
        target_ip = last_ip if last_ip and last_ip in white_list else None
        
        # 5. 尝试替换旧IP或添加新IP
        if target_ip:
            # 5.1 尝试替换旧IP
            print(f"发现旧IP {target_ip}，执行替换操作")
            
            # 删除旧IP
            if del_white_ip(target_ip):
                print(f"删除操作返回成功: {target_ip}")
                
                # 验证删除结果
                time.sleep(3)
                temp_white_list = get_white_list()
                if temp_white_list and target_ip not in temp_white_list:
                    print(f"✅ 删除成功: 目标IP {target_ip} 已移除")
                else:
                    print(f"⚠️ 删除失败: 目标IP {target_ip} 仍在白名单中")
            
            # 添加新IP
            if add_white_ip(current_ip):
                print(f"添加操作返回成功: {current_ip}")
            else:
                print(f"添加新IP失败: {current_ip}")
        else:
            # 5.2 直接添加新IP
            print("未找到有效旧IP，尝试直接添加")
            if add_white_ip(current_ip):
                print(f"添加操作返回成功: {current_ip}")
            else:
                print(f"添加新IP失败: {current_ip}")
        
        # 6. 验证操作结果
        print("等待5秒后验证操作结果...")
        time.sleep(5)
        
        new_white_list = get_white_list()
        if new_white_list:
            # 验证新IP是否已添加
            if current_ip in new_white_list:
                print(f"✅ 添加成功: 目标IP {current_ip} 已在白名单中")
                
                # 如果是替换操作，额外验证旧IP是否被移除
                if target_ip:
                    if target_ip not in new_white_list:
                        print(f"✅ 删除成功: 目标IP {target_ip} 已移除")
                    else:
                        print(f"⚠️ 删除失败: 目标IP {target_ip} 仍在白名单中")
                
                save_last_ip(current_ip)
                success = True
            else:
                print(f"❌ 添加失败: 目标IP {current_ip} 未在白名单中")
        else:
            print("❌ 验证失败: 无法获取白名单")
    
    # 7. 处理最终结果
    end_time = datetime.datetime.now()
    duration = (end_time - start_time).seconds
    print(f"\n## 执行结束... {end_time.strftime('%Y-%m-%d %H:%M:%S')}  耗时 {duration} 秒")
    
    if success:
        print("🟢 操作成功完成")
    else:
        error_msg = f"🔴 操作失败: 经过 {MAX_RETRIES} 次尝试仍未能更新白名单\n当前IP: {current_ip}\n请检查API接口是否可用"
        print(error_msg)
        push_notification(error_msg)
        sys.exit(1)

if __name__ == "__main__":
    main()